package com.xjoyt.pay.master.core.order.handle.create;

import java.util.List;
import java.util.Map;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.BooleanUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

import com.xjoyt.pay.dto.ExecuteResult;
import com.xjoyt.pay.gateway.params.OrderCreateParam;
import com.xjoyt.pay.gateway.params.OrderParam;
import com.xjoyt.pay.master.core.order.handle.AbstractOrderCreateHandle;
import com.xjoyt.pay.master.dto.OrderUrlResult;
import com.xjoyt.pay.master.po.DistributorRate;
import com.xjoyt.pay.master.po.Merchant;
import com.xjoyt.pay.master.po.MerchantChannel;
import com.xjoyt.pay.master.po.MerchantRate;
import com.xjoyt.pay.master.po.PayChannel;
import com.xjoyt.pay.master.repository.DistributorRateRepository;
import com.xjoyt.pay.master.repository.MerchantChannelRepository;
import com.xjoyt.pay.master.repository.MerchantRateRepository;
import com.xjoyt.pay.master.repository.MerchantRepository;
import com.xjoyt.pay.vo.PayType;
import com.xjoyt.pay.vo.TradeType;

/**
 * 验证order是否正确.
 * 
 * @author Administrator
 *
 */
@Component
@Scope("prototype")
public class ValidHandle extends AbstractOrderCreateHandle {

	@Autowired
	private MerchantRepository merchantRepository;

	@Autowired
	private MerchantRateRepository merchantRateRepository;

	@Autowired
	private DistributorRateRepository distributorRateRepository;

	@Autowired
	private MerchantChannelRepository merchantChannelRepository;

	@Override
	public ExecuteResult<OrderUrlResult> handle(OrderParam param, PayType payType, Map<String, Object> args) {
		//参数本地校验
		if (StringUtils.isBlank(param.outTradeNo))
			return ExecuteResult.fail("第三方订单号为空");
		
		//开始商户校验
		//TODO 订单厂商校验. 
		Merchant merchant = merchantRepository.findOne(param.merchantId);
		{
			if (merchant == null)
				return ExecuteResult.fail("商户不存在");
			putObject(merchant, args);
	
			if (BooleanUtils.isNotTrue(merchant.enabled))
				return ExecuteResult.fail("商户已被停用");
	
			if (merchant.distributor == null)
				return ExecuteResult.fail("代理商不存在");
	
			if (BooleanUtils.isNotTrue(merchant.enabled))
				return ExecuteResult.fail("代理商已被停用");
	
			if (merchant.distributor.company == null)
				return ExecuteResult.fail("所属机构不存在");
	
			if (BooleanUtils.isNotTrue(merchant.distributor.company.enabled))
				return ExecuteResult.fail("机构已被停用");
	
			if (repository.findOneByMerchantIdAndOutTradeNo(merchant.id, param.outTradeNo) != null)
				return ExecuteResult.fail("订单号重复");
	
			MerchantRate merchantRate = merchantRateRepository.findOneByMerchantIdAndType(merchant.id, payType);
			if (merchantRate == null)
				return ExecuteResult.fail("商户费率未设置");
			
			putObject(merchantRate, args);
			
			DistributorRate distributorRate = distributorRateRepository
					.findOneByDistributorIdAndType(merchant.distributor.id, payType);
			if (distributorRate == null)
				return ExecuteResult.fail("代理商费率未设置");
			putObject(distributorRate, args);
		}
		

		//支付通道校验

		MerchantChannel merchantChannel = getMerchantChannel(merchant, payType, param.type);
		if (merchantChannel == null)
			return ExecuteResult.fail("未找到可用支付通道");
		putObject(merchantChannel, args);
		
		PayChannel payChannel = getPayChannel(merchantChannel, payType, param.type);
		if (payChannel == null) {
			return ExecuteResult.fail("支付通道选失效");
		}
		putObject(payChannel, args);

		return getNext().handle(param, payType, args);
	}

	private MerchantChannel getMerchantChannel(Merchant merchant, PayType payType, TradeType tradeType) {
		List<MerchantChannel> list = merchantChannelRepository.findAllByPay(merchant.id, payType, tradeType);
		return CollectionUtils.isEmpty(list) ? null : list.get(0);
	}

	private PayChannel getPayChannel(MerchantChannel merchantChannel, PayType payType, TradeType tradeType) {
		if (merchantChannel.channel == null || CollectionUtils.isEmpty(merchantChannel.channel.channels)) {
			return null;
		}
		for (PayChannel item : merchantChannel.channel.channels) {
			if (payType.equals(item.payType) && tradeType.equals(item.tradeType) && StringUtils.isNotBlank(item.url)) {
				return item;
			}
		}
		return null;
	}

}
